﻿using Control.Client.Message;
using Control.Client.Utilities;
using Control.Enum;
using Control.Helper;
using Control.Message;

using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using TouchSocket.Core;
using TouchSocket.Http.WebSockets;

namespace Control.WeSocket
{
    public class WebSocketPlugin : PluginBase, IWebSocketReceivedPlugin
    {
        private CancellationTokenSource? _cancellationTokenSource;

        public async Task OnWebSocketReceived(IWebSocket webSocket, WSDataFrameEventArgs e)
        {

            switch (e.DataFrame.Opcode)
            {
                case WSDataType.Text:
                    {

                        string msg = e.DataFrame.ToText();

                        if (msg == RequestType.ShowImage.ToString())
                        {
                           // BitmapData desktopData = null;
                          
                            var monitorBounds = ScreenHelper.GetBounds(0);
                            var resolution = new Resolution { Height = monitorBounds.Height, Width = monitorBounds.Width };
                      
                            _cancellationTokenSource = new CancellationTokenSource();
                            CancellationToken token = _cancellationTokenSource.Token;
#pragma warning disable CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法
                            Task.Run(async () =>
                            {
                               // using (UnsafeStreamCodec unsafeStreamCodec = new(100, 0, resolution))
                                {


                                    while (!token.IsCancellationRequested)
                                    {
                                        using (var desktop = ScreenHelper.CaptureScreen(0))
                                        {
                             //               desktopData = desktop.LockBits(new Rectangle(0, 0, desktop.Width, desktop.Height),
                             //ImageLockMode.ReadWrite, desktop.PixelFormat);
                                            try
                                            {
                                               using (MemoryStream stream = new MemoryStream()) {
                                                    //                 unsafeStreamCodec.CodeImage(desktopData.Scan0,

                                                    //new Rectangle(0, 0, desktop.Width, desktop.Height),
                                                    //new Size(desktop.Width, desktop.Height),
                                                    //desktop.PixelFormat, stream);
                                                    desktop.Save(stream, ImageFormat.Png);
                                                    await  webSocket.SendAsync(stream.ToArray());
                                                }
                                            }
                                            finally {
                                              //  desktop.UnlockBits(desktopData);
                                            }
                                         
                                            


                                           
                                        }
                                        await Task.Delay(100);
                                    }
                                }
                            }, token);

#pragma warning restore CS4014 // 由于此调用不会等待，因此在调用完成前将继续执行当前方法
                        }
                        else
                        {
                            ReceiveMessage? receiveMessage = JsonConvert.DeserializeObject<ReceiveMessage>(msg);
                            if (receiveMessage != null && receiveMessage.Operate == (int)RequestType.Mouse)
                            {
                                DoMouseEvent? mouseEvent = JsonConvert.DeserializeObject<DoMouseEvent>(receiveMessage.Message);
                                Console.WriteLine($"收到消息：{receiveMessage.Message}");
                                if (mouseEvent != null)
                                {
                                    MouseEvent(message: mouseEvent);
                                }

                            }
                            else if (receiveMessage != null && receiveMessage.Operate == (int)RequestType.Keyboard)
                            {

                            }
                        }

                    }
                    break;
                case WSDataType.Binary:
                    {
                        Console.WriteLine("收到二进制数据");
                    }
                    break;
                case WSDataType.Ping:
                    {
                        Console.WriteLine("收到Ping");
                    }
                    break;
                case WSDataType.Pong:
                    {
                        Console.WriteLine("收到Pong");
                    }
                    break;
                case WSDataType.Close:
                    {
                        _cancellationTokenSource?.Cancel();
                        Console.WriteLine("收到Close");
                    }
                    break;
            }
            await e.InvokeNext();
        }

        private byte[] BitmapToByteArray(Bitmap bitmap)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                bitmap.Save(ms, ImageFormat.Png);
                return ms.ToArray();
            }
        }
        private void MouseEvent(DoMouseEvent message)
        {
            try
            {
                Screen[] allScreens = Screen.AllScreens;
                int offsetX = allScreens[message.MonitorIndex].Bounds.X;
                int offsetY = allScreens[message.MonitorIndex].Bounds.Y;
                Point p = new Point(message.X + offsetX, message.Y + offsetY);

                // Disable screensaver if active before input
                switch (message.Action)
                {
                    case (int)MouseAction.LeftDown:
                    case (int)MouseAction.LeftUp:
                    case (int)MouseAction.RightDown:
                    case (int)MouseAction.RightUp:
                    case (int)MouseAction.MoveCursor:
                        if (NativeMethodsHelper.IsScreensaverActive())
                            NativeMethodsHelper.DisableScreensaver();
                        break;
                }

                switch (message.Action)
                {
                    case (int)MouseAction.LeftDown:
                    case (int)MouseAction.LeftUp:
                        NativeMethodsHelper.DoMouseLeftClick(p, message.IsMouseDown);
                        break;
                    case (int)MouseAction.RightDown:
                    case (int)MouseAction.RightUp:
                        NativeMethodsHelper.DoMouseRightClick(p, message.IsMouseDown);
                        break;
                    case (int)MouseAction.MoveCursor:
                        NativeMethodsHelper.DoMouseMove(p);
                        break;
                    case (int)MouseAction.ScrollDown:
                        NativeMethodsHelper.DoMouseScroll(p, true);
                        break;
                    case (int)MouseAction.ScrollUp:
                        NativeMethodsHelper.DoMouseScroll(p, false);
                        break;
                }
            }
            catch
            {
            }
        }

    }
}
